package com.suray.basic.wcs.plc.utils;

import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
import okio.Timeout;

import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author shaozn
 */
public class LongConnSendUtil {
    /**
     * 储存实例的容器
     */
    private static Map<NetAddress, LongConnSendUtil> socketMap = new HashMap<>();
    private NetAddress netAddress;
    private Socket socket = null;
    BufferedSink out = null;
    BufferedSource in = null;

    /**
     * 构造函数
     *
     * @param netAddress 网络地址
     * @throws IOException
     */
    public LongConnSendUtil(NetAddress netAddress) throws IOException {
        this.netAddress = netAddress;
        linkSocket();
    }

    /**
     * 单例
     *
     * @param netAddress
     * @return 一个长连接
     * @throws IOException
     */
    public synchronized static LongConnSendUtil getSocketSendUtil(NetAddress netAddress) throws IOException {
        LongConnSendUtil longConnSendUtil = socketMap.get(netAddress);
        if (longConnSendUtil == null) {
            longConnSendUtil = new LongConnSendUtil(netAddress);
            socketMap.put(netAddress, longConnSendUtil);
        }
        return longConnSendUtil;

    }

    /**
     * 创建连接
     *
     * @throws IOException
     */
    public void linkSocket() throws IOException {
        if (socket == null || socket.isClosed()) {
            socket = new Socket(netAddress.getIp(), netAddress.getPort());
            out = Okio.buffer(Okio.sink(socket));
            in = Okio.buffer(Okio.source(socket));
        }
    }

    /**
     * 终止连接
     *
     * @return
     */
    private boolean terminate() {
        try {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            in = null;
            out = null;
            socket = null;
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    /**
     * 发送
     *
     * @param bs 需要发送的字节
     * @return
     */
    public synchronized byte[] send(byte[] bs) throws IOException {
        try {
            linkSocket();
            Timeout timeout = in.timeout();
            timeout.timeout(5000, TimeUnit.MILLISECONDS);
            out.write(bs);
            out.flush();
            return getReturnBytes();
        } catch (Exception e) {
            terminate();
            throw new IOException();
        }
    }

    /**
     * 获取网络地址
     * @return
     */
    public NetAddress getNetAddress() {
        return netAddress;
    }

    public void setNetAddress(NetAddress netAddress) {
        this.netAddress = netAddress;
    }

    /**
     * read
     *
     * @return
     * @throws IOException
     */
    public byte[] getReturnBytes() throws IOException {
        //定义最大数组
        byte[] buff = new byte[1024];
        int maxNum = in.read(buff);

        if (maxNum < 0) {
            throw new IOException("通讯异常：readData size = " + maxNum);
        }

        byte[] b = new byte[maxNum];
        System.arraycopy(buff, 0, b, 0, maxNum);
        return b;
    }
}
